package samples.d2.polygons 
{
	import color.HSL;
	import flash.display.InteractiveObject;
	import flash.geom.Point;
	import flash.geom.Rectangle;
	import flash.utils.setInterval;
	import samples.BaseSample;
	import shapes.shapes2D.distribution.Circular;
	import shapes.shapes2D.distribution.Frame;
	import shapes.shapes2D.polygon.ConvexHull;
	import shapes.shapes2D.polygon.EarCutting;
	import shapes.shapes2D.polygon.Edge;
	import shapes.shapes2D.polygon.Intersection;
	import shapes.shapes2D.polygon.Polygon;
	import shapes.shapes2D.polygon.Simplify;
	import shapes.shapes2D.polygon.Skeleton;
	import shapes.shapes2D.polygon.triangle.Triangle;
	import shapes.shapes2D.polygon.Triangulation;
	import utils.GeomUtils;
	
	/**
	 * @author Nicolas Barradeau
	 * http://en.nicoptere.net
	 */
	public class Polygon6 extends BaseSample
	{
		
		private var poly:Polygon;
		public function Polygon6() 
		{
			
			poly = new Polygon( 0,0, new Circular( new Point( sw/2, sh/2 ), 200, 200 ).distribute( 150, false, 100 ).reverse() );
			poly = new Coq( sw / 2, sh / 2 - 75, 2.5 );
			
			
			
			graphics.lineStyle( 10, 0x003399, 1 );
			plotLines( poly.points );
			
			graphics.lineStyle( 0, 0xFFFFFF );
			plotPoints( poly.points );
			
			var points:Vector.<Point> = ConvexHull.process( poly.points );
			var values:Vector.<DistObject> = new Vector.<DistObject>();
			var maxDist:Number = Number.NEGATIVE_INFINITY;
			var dist:Number;
			var ce:Point = poly.centroid;
			var p:Point;
			for ( var i:int = 0; i < points.length; i++ )
			{
				
				p = points[ i ];
				dist = GeomUtils.distance( ce, p );
				values.push( new DistObject( dist, i ) );
				if ( dist > maxDist ) maxDist = dist;
				
			}
			
			graphics.lineStyle( 0, 0x00FF00 );
			plotLines( points );
			var n:Number
			var left:Number = sw / 2 - 300;
			var longest:Vector.<DistObject> = new Vector.<DistObject>();
			var pv:Number = values[ values.length- 1 ].distance;
			var cv:Number = values[ 0 ].distance;
			var nv:Number = values[ 1 ].distance;
			
			for ( i = 1; i < values.length; i++ )
			{
				
				pv = values[ i - 1 ].distance;
				cv = values[ i ].distance;
				nv = values[ ( i + 1 ) % values.length ].distance;
				
				graphics.lineStyle( 0, 0xFFffff, .1 );
				if ( cv >= pv && cv >= nv )//pic haut 
				{
					graphics.lineStyle( 0, 0x00FF00 );
					longest.push( values[ i ] );
				}
				graphics.moveTo( points[ values[ i ].id ].x, points[ values[ i ].id ].y );
				graphics.lineTo( ce.x, ce.y  );
				
				n = values[ i ].distance;
				graphics.moveTo( left + i * ( 600 / values.length ), sh - 50 );
				graphics.lineTo( left + i * ( 600 / values.length ), sh - 50 - GeomUtils.map( n, 0, maxDist, 0, 100 )  );
				
			}
			graphics.lineStyle( 4, 0xFFFF00 );
			
			if ( longest.length <= 1 ) return;
			
			if ( longest.length == 2 )
			{
				var diameter:Edge = new Edge( points[ longest[ 0 ].id ], points[ longest[ 1 ].id ]);
				graphics.drawCircle( diameter.center.x, diameter.center.y, diameter.length * .5 );
				
				return;
			}
			
			//longer first
			longest.sort( distanceSort ).reverse();
			
			var pts:Vector.<Point> = new Vector.<Point>();
			for ( i = 0; i < 3; i++ )
			{
				
				pts.push( points[ longest[ i ].id ] );
				graphics.moveTo( pts[ i ].x, pts[ i ].y );
				graphics.lineTo( ce.x, ce.y  );
				
			}
			
			var tri:Triangle = new Triangle( pts[ 0 ], pts[ 1 ], pts[ 2 ]);
			
			circumcircle( tri );
			
		}
		
		private function circumcircle(tri:Triangle):void 
		{
			
			var e0:Edge = new Edge( tri.edges[ 0 ].center,  tri.p1 ).leftNormal;
			var e1:Edge = new Edge( tri.edges[ 1 ].center,  tri.p2 ).leftNormal;
			var ce:Point = Intersection.lineIntersectLine( e0.p0, e0.p1, e1.p0, e1.p1, false, false );
			
			if ( ce != null )
			{
				var r:Number = GeomUtils.distance( ce, tri.p0 );
				graphics.drawCircle( ce.x, ce.y, r );
			}
			
		}
		
		private function distanceSort( a:DistObject, b:DistObject ):Number
		{
			
			return ( a.distance < b.distance)? -1:1;
			
		}
		
		private function addPoint():void 
		{
			var i:int = 10;
			while ( i-- )
			{
				var p:Point = new Point( Math.random() * sw, Math.random() * sh );
				
				graphics.lineStyle( 4, 0xFF0000 );
				if ( poly.contains( p ) )
				{
					graphics.lineStyle( 4, 0x00FF00 );
				}
				graphics.moveTo( p.x, p.y );
				graphics.lineTo( p.x+.5, p.y );
			}
			
		}
		
		private function plotPoints( points:Vector.<Point>):void
		{
			
			var p:Point = points[ 0 ];
			for each( p in points )
			{
				graphics.drawCircle( p.x, p.y, 2 );
			}
			
		}
		
		private function plotLines( points:Vector.<Point>):void
		{
			if ( points.length == 0 ) return;
			var p:Point = points[ 0 ];
			graphics.moveTo( p.x, p.y );
			
			for each( p in points )
			{
				
				graphics.lineTo( p.x, p.y );
				
			}
			graphics.lineTo( points[ 0 ].x, points[ 0 ].y );
			
		}
		
		private function plotEdges( edges:Vector.<Edge>):void
		{
			if ( edges.length == 0 ) return;
			
			var e:Edge = edges[ 0 ];
			
			for each( e in edges )
			{
				
				graphics.moveTo( e.p0.x, e.p0.y );
				graphics.lineTo( e.p1.x, e.p1.y );
				
			}
			
		}
		private function plotNormals( edges:Vector.<Edge>, left:Boolean = true ):void
		{
			if ( edges.length == 0 ) return;
			
			var e:Edge;
			var n:Edge;
			
			for each( e in edges )
			{
				if ( left ) n = e.leftNormal;
				else n = e.rightNormal;
				
				graphics.moveTo( n.p0.x, n.p0.y );
				graphics.lineTo( n.p1.x, n.p1.y );
				
			}
			
		}
		
	}

}
class DistObject
{
	private var _distance:Number;
	private var _id:int;
	public function DistObject( distance:Number, id:int )
	{
		this._id = id;
		this._distance = distance;
		
	}
	
	public function get distance():Number { return _distance; }
	
	public function set distance(value:Number):void 
	{
		_distance = value;
	}
	
	public function get id():int { return _id; }
	
	public function set id(value:int):void 
	{
		_id = value;
	}
}